#include <string.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>       
#include <fcntl.h>
#include<stdlib.h>
#include<termios.h>

#define EINK_DEVICE "/dev/ttyACM0"
#define CPUTEMP_FILE "/sys/class/thermal/thermal_zone2/temp"
#define IPADDR_FILE "/etc/NetworkManager/system-connections/Wired connection 1"
#define OSNAMESZ 128
#define MEM_TOTAL_CMD "cat /proc/meminfo  | grep \"MemTotal:\" | awk '{print $2}' | cut -c 1-"
#define MEM_AVAILBLE_CMD "cat /proc/meminfo  | grep \"MemAvailable:\" | awk '{print $2}' | cut -c 1-"

#define SSD_TOTAL_CMD "df /dev/nvme0n1p1 | grep \"nvme0n1p1\" | awk '{print $2}' | cut -c 1-"
#define SSD_USE_CMD "df /dev/nvme0n1p1 | grep \"nvme0n1p1\" | awk '{print $3}' | cut -c 1-"
#define SSD_PERCENT_CMD "df /dev/nvme0n1p1 | grep \"nvme0n1p1\" | awk '{print $5}' | cut -c 1-"

#define DISK_TOTAL_CMD "df /dev/sda2 | grep \"sda2\" | awk '{print $2}' | cut -c 1-"
#define DISK_USE_CMD "df /dev/sda2 | grep \"sda2\" | awk '{print $3}' | cut -c 1-"
#define DISK_PERCENT_CMD "df /dev/sda2 | grep \"sda2\" | awk '{print $5}' | cut -c 1-"
typedef struct MenInfo {
	 unsigned int  use;
	 unsigned int  total;
	 unsigned int  use_percent;
}MemInfo;

typedef struct Storage{
         unsigned int  ssd_use;
	 unsigned int  ssd_total;
	 unsigned int  ssd_percent;
	 unsigned int  disk_use;
	 unsigned int  disk_total;
	 unsigned int  disk_percent;
}Storage;

void GetIpaddr(char * addr){
	FILE *fp;
	fp = popen("ifconfig enp0s31f6 | grep \"inet \" | awk \'{print $2}\' | cut -c 1-", "r");
	fgets(addr,16,fp);
	pclose(fp);
}

int getcpuutilization(unsigned char * cpuutilization,unsigned char * temp)
{
	int sum1[2]={0};
	int sum2[2]={0};
	int i=0;
	for(i=0;i<2;i++){
		if(i==1)
		{
			usleep(200*1000);
		}
		FILE *stream1=NULL;
		FILE *stream2=NULL;
		FILE *stream3=NULL;
		FILE *stream4=NULL;
		FILE *stream5=NULL;
		FILE *stream6=NULL;
		FILE *stream7=NULL;
		FILE *stream8=NULL;
		FILE *stream9=NULL;
		char COMMAND1[OSNAMESZ]="cat /proc/stat | sed -n 1p | awk '{print $2}'";
		char COMMAND2[OSNAMESZ]="cat /proc/stat | sed -n 1p | awk '{print $3}'";
		char COMMAND3[OSNAMESZ]="cat /proc/stat | sed -n 1p | awk '{print $4}'";
		char COMMAND4[OSNAMESZ]="cat /proc/stat | sed -n 1p | awk '{print $5}'";
		char COMMAND5[OSNAMESZ]="cat /proc/stat | sed -n 1p | awk '{print $6}'";
		char COMMAND6[OSNAMESZ]="cat /proc/stat | sed -n 1p | awk '{print $7}'";
		char COMMAND7[OSNAMESZ]="cat /proc/stat | sed -n 1p | awk '{print $8}'";
		char COMMAND8[OSNAMESZ]="cat /proc/stat | sed -n 1p | awk '{print $9}'";
		char COMMAND9[OSNAMESZ]="cat /proc/stat | sed -n 1p | awk '{print $10}'";
		char buff1[OSNAMESZ]={0};
		char buff2[OSNAMESZ]={0};
		char buff3[OSNAMESZ]={0};
		char buff4[OSNAMESZ]={0};
		char buff5[OSNAMESZ]={0};
		char buff6[OSNAMESZ]={0};
		char buff7[OSNAMESZ]={0};
		char buff8[OSNAMESZ]={0};
		char buff9[OSNAMESZ]={0};
		int cpudata1;
		int cpudata2;
		int cpudata3;
		int cpudata4;
		int cpudata5;
		int cpudata6;
		int cpudata7;
		int cpudata8;
		int cpudata9;

		stream1=popen(COMMAND1,"r");
		signal(SIGCHLD,SIG_IGN);
		stream2=popen(COMMAND2,"r");
		signal(SIGCHLD,SIG_IGN);
		stream3=popen(COMMAND3,"r");
		signal(SIGCHLD,SIG_IGN);
		stream4=popen(COMMAND4,"r");
		signal(SIGCHLD,SIG_IGN);
		stream5=popen(COMMAND5,"r");
		signal(SIGCHLD,SIG_IGN);
		stream6=popen(COMMAND6,"r");
		signal(SIGCHLD,SIG_IGN);
		stream7=popen(COMMAND7,"r");
		signal(SIGCHLD,SIG_IGN);
		stream8=popen(COMMAND8,"r");
		signal(SIGCHLD,SIG_IGN);
		stream9=popen(COMMAND9,"r");
		signal(SIGCHLD,SIG_IGN);
		if(!stream1 || !stream2 || !stream3 || !stream4 || !stream5 || !stream6 || !stream7 || !stream8 || !stream9)
		{
			return -1;
		}
		fread(buff1,sizeof(char),OSNAMESZ,stream1);
		pclose(stream1);
		fread(buff2,sizeof(char),OSNAMESZ,stream2);
		pclose(stream2);
		fread(buff3,sizeof(char),OSNAMESZ,stream3);
		pclose(stream3);
		fread(buff4,sizeof(char),OSNAMESZ,stream4);
		pclose(stream4);
		fread(buff5,sizeof(char),OSNAMESZ,stream5);
		pclose(stream5);
		fread(buff6,sizeof(char),OSNAMESZ,stream6);
		pclose(stream6);
		fread(buff7,sizeof(char),OSNAMESZ,stream7);
		pclose(stream7);
		fread(buff8,sizeof(char),OSNAMESZ,stream8);
		pclose(stream8);
		fread(buff9,sizeof(char),OSNAMESZ,stream9);
		pclose(stream9);
		if(strlen(buff1)==0 || strlen(buff2)==0 || strlen(buff3)==0 || strlen(buff4)==0 || strlen(buff5)==0 || strlen(buff6)==0 || strlen(buff7)==0 || strlen(buff8)==0 || strlen(buff9)==0)
		{
			return -1;
		}
		cpudata1=atoi(buff1);
		cpudata2=atoi(buff2);
		cpudata3=atoi(buff3);
		cpudata4=atoi(buff4);
		cpudata5=atoi(buff5);
		cpudata6=atoi(buff6);
		cpudata7=atoi(buff7);
		cpudata8=atoi(buff8);
		cpudata9=atoi(buff9);
		sum1[i]=cpudata1+cpudata2+cpudata3;
		sum2[i]=cpudata1+cpudata2+cpudata3+cpudata4+cpudata5+cpudata6+cpudata7+cpudata8+cpudata9;
	}
	*cpuutilization =(float)(sum1[1]-sum1[0])/(sum2[1]-sum2[0])*100;

	//temp
	int temp_fb= open(CPUTEMP_FILE,O_RDONLY);
	char temp_rdbuf[10];
	read(temp_fb,temp_rdbuf,10);
	*temp = atoi(temp_rdbuf)/1000;
	return 0;
}

int GetMemInfo(MemInfo * meminfo){
	
	FILE *total_fb ,*availble_fb;
	char total_buf[30],availble_buf[30];
	unsigned int  total, use;; 
        total_fb = popen(MEM_TOTAL_CMD, "r");
	fgets(total_buf,30,total_fb);
	total = atoi(total_buf)/1024;
	pclose(total_fb);

        availble_fb = popen(MEM_AVAILBLE_CMD, "r");
	fgets(availble_buf,30,availble_fb);
	use  = total - atoi(availble_buf)/1024;
	pclose(availble_fb);


	meminfo->use = use;
	meminfo->total = total;
	meminfo->use_percent = ((float)use/total) * 100;

	return 0;
}

int GetStorageInfo(Storage * storage){

	FILE * ssd_total_fb, *ssd_use_fb, *ssd_percent_fb;
	FILE * disk_total_fb, * disk_use_fb, * disk_percent_fb;
	char ssd_total_buf[50], ssd_use_buf[50], ssd_percent_buf[50];
	char disk_total_buf[50], disk_use_buf[50], disk_percent_buf[50];
        ssd_total_fb = popen(SSD_TOTAL_CMD, "r");
        ssd_use_fb = popen(SSD_USE_CMD, "r");
        ssd_percent_fb = popen(SSD_PERCENT_CMD, "r");
        disk_total_fb = popen(DISK_TOTAL_CMD, "r");
        disk_use_fb = popen(DISK_USE_CMD, "r");
        disk_percent_fb = popen(DISK_PERCENT_CMD, "r");
	fgets(ssd_total_buf,50,ssd_total_fb);
	fgets(ssd_use_buf,50,ssd_use_fb);
	fgets(ssd_percent_buf,50,ssd_percent_fb);
	fgets(disk_total_buf,50,disk_total_fb);
	fgets(disk_use_buf,50,disk_use_fb);
	fgets(disk_percent_buf,50,disk_percent_fb);
	storage->ssd_use = (unsigned int )(float)atoi(ssd_use_buf)/1024/1024;
	storage->ssd_total = (unsigned int )(float)atoi(ssd_total_buf)/1024/1024;
	storage->ssd_percent = atoi(ssd_percent_buf);
	storage->disk_use = (unsigned int )(float)atoi(disk_use_buf)/1024/1024;
	storage->disk_total = (unsigned int )(float)atoi(disk_total_buf)/1024/1024;
	storage->disk_percent = atoi(disk_percent_buf);
	pclose(ssd_total_fb);
	pclose(ssd_use_fb);
	pclose(ssd_percent_fb);
	pclose(disk_total_fb);
	pclose(disk_use_fb);
	pclose(disk_percent_fb);

}

int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
{
	 struct termios newtio,oldtio;
	 if  ( tcgetattr( fd,&oldtio)  !=  0) {
	  perror("SetupSerial 1");
	  return -1;
	 }
	 bzero( &newtio, sizeof( newtio ) );
	 newtio.c_cflag  |=  CLOCAL | CREAD; //CLOCAL:忽略modem控制线  CREAD：打开接受者
	 newtio.c_cflag &= ~CSIZE; //字符长度掩码。取值为：CS5，CS6，CS7或CS8

	 switch( nBits )
	 {
	 case 7:
	  newtio.c_cflag |= CS7;
	  break;
	 case 8:
	  newtio.c_cflag |= CS8;
	  break;
	 }

	 switch( nEvent )
	 {
	 case 'O':
	  newtio.c_cflag |= PARENB; //允许输出产生奇偶信息以及输入到奇偶校验
	  newtio.c_cflag |= PARODD;  //输入和输出是奇及校验
	  newtio.c_iflag |= (INPCK | ISTRIP); // INPACK:启用输入奇偶检测；ISTRIP：去掉第八位
	  break;
	 case 'E':
	  newtio.c_iflag |= (INPCK | ISTRIP);
	  newtio.c_cflag |= PARENB;
	  newtio.c_cflag &= ~PARODD;
	  break;
	 case 'N':
	  newtio.c_cflag &= ~PARENB;
	  break;
	 }

	 switch( nSpeed )
	 {
	 case 2400:
	  cfsetispeed(&newtio, B2400);
	  cfsetospeed(&newtio, B2400);
	  break;
	 case 4800:
	  cfsetispeed(&newtio, B4800);
	  cfsetospeed(&newtio, B4800);
	  break;
	 case 9600:
	  cfsetispeed(&newtio, B9600);
	  cfsetospeed(&newtio, B9600);
	  break;
	 case 115200:
	  cfsetispeed(&newtio, B115200);
	  cfsetospeed(&newtio, B115200);
	  break;
	 case 460800:
	  cfsetispeed(&newtio, B460800);
	  cfsetospeed(&newtio, B460800);
	  break;
	 default:
	  cfsetispeed(&newtio, B9600);
	  cfsetospeed(&newtio, B9600);
	  break;
	 }

	 if( nStop == 1 )
	  newtio.c_cflag &=  ~CSTOPB; //CSTOPB:设置两个停止位，而不是一个
	 else if ( nStop == 2 )
	 newtio.c_cflag |=  CSTOPB;

	 newtio.c_cc[VTIME]  = 0; //VTIME:非cannoical模式读时的延时，以十分之一秒位单位
	 newtio.c_cc[VMIN] = 0; //VMIN:非canonical模式读到最小字符数
	 tcflush(fd,TCIFLUSH); // 改变在所有写入 fd 引用的对象的输出都被传输后生效，所有已接受但未读入的输入都在改变发生前丢弃。
	 if((tcsetattr(fd,TCSANOW,&newtio))!=0) //TCSANOW:改变立即发生
	 {
	  perror("com set error");
	  return -1;
	 }
	 printf("set done!\n\r");
	 return 0;
}

int main(int argc, char* argv[])
{

	int uart_fb, nset, nread, ret;
	char Ipaddr[16], Ipaddr_old[16]; 
	unsigned char sendbuf[50];
	int sendbuf_len, ipaddr_len=0;
	unsigned char cpu_use,temp;
	int i = 0;
	uart_fb = open(EINK_DEVICE,O_RDWR);
	if(uart_fb == -1){ 
	  printf("device open faild , exit!\n");
	  exit(1);
	}
        nset = set_opt(uart_fb, 115200, 9, 'N', 1);
	if(nset == -1){
	    exit(1);
	    printf("set_opt error\n");
	}
	sendbuf[0] = 0xaa;
	sendbuf[1] = 0xf0;
	sendbuf[2] = 0x55;
        ret = write(uart_fb, sendbuf, 3);
        usleep(3*1000*1000);
	GetIpaddr(Ipaddr);
	sendbuf[0] =0xaa;
	sendbuf[1] =0x01;
	while((Ipaddr[i] >= 0x30 && Ipaddr[i] <= 0x39 || Ipaddr[i] == 0x2e) && i < 15){    
	   sendbuf[i + 2] = Ipaddr[i];	
	    ipaddr_len++;
	    i++;
	}
	sendbuf[ipaddr_len+2] = 55;
        ret = write(uart_fb, sendbuf, ipaddr_len+2+1);
	strcpy(Ipaddr_old, Ipaddr);
	MemInfo meminfo;
	Storage storage;
	while(1){
		/*
		getcpuutilization(&cpu_use,&temp);
		printf("cpu=%u temp=%u\n",cpu_use, temp);
		sendbuf[0] = 0xaa;
		sendbuf[1] = 0x02;
		sendbuf[2] = temp;
		sendbuf[3] = cpu_use;
		sendbuf[4] = 0x55;
                ret = write(uart_fb, sendbuf, 5);

		GetMemInfo(&meminfo);
		printf("meminfo: use = %dMB total = %dMB %d%\n", meminfo.use, meminfo.total, meminfo.use_percent);
		sendbuf[0] = 0xaa;
		sendbuf[1] = 0x03;
		sendbuf[2] = (meminfo.use >> 8) & 0x00ff;
		sendbuf[3] = meminfo.use & 0x00ff;
		sendbuf[4] = (meminfo.total >> 8) & 0xff;
		sendbuf[5] = meminfo.total & 0xff;
		sendbuf[6] = meminfo.use_percent;
		sendbuf[7] = 0x55;
		usleep(1200*1000);
		ret = write(uart_fb, sendbuf,8);

		GetStorageInfo(&storage);
		sendbuf[0] = 0xaa;
		sendbuf[1] = 0x04;
		sendbuf[2] = (storage.ssd_use >> 8) & 0xff;
		sendbuf[3] = storage.ssd_use & 0xff;
		sendbuf[4] = (storage.ssd_total >> 8) & 0xff;
		sendbuf[5] = storage.ssd_total & 0xff;
		sendbuf[6] = storage.ssd_percent;
		sendbuf[7] = (storage.disk_use >> 8) & 0xff;
		sendbuf[8] = storage.disk_use & 0xff;
		sendbuf[9] = (storage.disk_total >> 8) & 0xff;
		sendbuf[10] = storage.disk_total & 0xff;
		sendbuf[11] = storage.disk_percent;
		sendbuf[12] = 0x55;
		usleep(1200*1000);
		ret = write(uart_fb, sendbuf,13);
		printf("ssd : use= %dGB total %dGB %d%\n" , storage.ssd_use, storage.ssd_total, storage.ssd_percent);
		printf("disk : use= %dGB total %dGB %d%\n" , storage.disk_use, storage.disk_total, storage.disk_percent);
	        usleep(1200*1000);*/

                usleep(1200*1000);
		GetMemInfo(&meminfo);
		//printf("meminfo: use = %dMB total = %dMB %d%\n", meminfo.use, meminfo.total, meminfo.use_percent);
		sendbuf[0] = 0xaa;
		sendbuf[1] = 0x06;
		sendbuf[2] = (meminfo.use >> 8) & 0x00ff;
		sendbuf[3] = meminfo.use & 0x00ff;
		sendbuf[4] = (meminfo.total >> 8) & 0xff;
		sendbuf[5] = meminfo.total & 0xff;
		sendbuf[6] = meminfo.use_percent;
		getcpuutilization(&cpu_use,&temp);
		//printf("cpu=%u temp=%u\n",cpu_use, temp);
		sendbuf[7] = temp;
		sendbuf[8] = cpu_use;
		GetStorageInfo(&storage);
		sendbuf[9] = (storage.ssd_use >> 8) & 0xff;
		sendbuf[10] = storage.ssd_use & 0xff;
		sendbuf[11] = (storage.ssd_total >> 8) & 0xff;
		sendbuf[12] = storage.ssd_total & 0xff;
		sendbuf[13] = storage.ssd_percent;
		sendbuf[14] = (storage.disk_use >> 8) & 0xff;
		sendbuf[15] = storage.disk_use & 0xff;
		sendbuf[16] = (storage.disk_total >> 8) & 0xff;
		sendbuf[17] = storage.disk_total & 0xff;
		sendbuf[18] = storage.disk_percent;
		sendbuf[19] = 0x55;
		//printf("ssd : use= %dGB total %dGB %d%\n" , storage.ssd_use, storage.ssd_total, storage.ssd_percent);
		//printf("disk : use= %dGB total %dGB %d%\n" , storage.disk_use, storage.disk_total, storage.disk_percent);
		ret = write(uart_fb, sendbuf,20);

		//check ip
		GetIpaddr(Ipaddr);
		if(strcmp(Ipaddr, Ipaddr_old)){
			GetIpaddr(Ipaddr);
			sendbuf[0] =0xaa;
			sendbuf[1] =0x01;
			i = 0;
			ipaddr_len = 0;
			while((Ipaddr[i] >= 0x30 && Ipaddr[i] <= 0x39 || Ipaddr[i] == 0x2e) && i < 15){    
				sendbuf[i + 2] = Ipaddr[i];	
				ipaddr_len++;
				i++;
			}
			sendbuf[ipaddr_len+2] = 55;
			usleep(1200*1000);
			ret = write(uart_fb, sendbuf, ipaddr_len+2+1);
			strcpy(Ipaddr_old, Ipaddr);
		}


	}
	close(uart_fb);
	return 0;

}



